home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 1_2002.ISO / Data / Zips / HTMLLabel 245208122001.psc / HTMLLabel.ctl (.txt)
Encoding:
Visual Basic Form  |  2001-08-12  |  90.4 KB  |  1,962 lines

  1. VERSION 5.00
  2. Begin VB.UserControl HTMLLabel 
  3.    BorderStyle     =   1  'Fixed Single
  4.    ClientHeight    =   675
  5.    ClientLeft      =   0
  6.    ClientTop       =   0
  7.    ClientWidth     =   1635
  8.    ScaleHeight     =   675
  9.    ScaleWidth      =   1635
  10.    Begin VB.PictureBox picViewPort 
  11.       Appearance      =   0  'Flat
  12.       BackColor       =   &H80000005&
  13.       BorderStyle     =   0  'None
  14.       CausesValidation=   0   'False
  15.       ClipControls    =   0   'False
  16.       ForeColor       =   &H80000008&
  17.       Height          =   525
  18.       Left            =   0
  19.       ScaleHeight     =   35
  20.       ScaleMode       =   3  'Pixel
  21.       ScaleWidth      =   47
  22.       TabIndex        =   2
  23.       Top             =   0
  24.       Width           =   705
  25.    End
  26.    Begin VB.Timer tmrHyperlinkClick 
  27.       Enabled         =   0   'False
  28.       Interval        =   250
  29.       Left            =   210
  30.       Top             =   90
  31.    End
  32.    Begin VB.VScrollBar vscScroll 
  33.       Height          =   525
  34.       Left            =   1290
  35.       TabIndex        =   1
  36.       TabStop         =   0   'False
  37.       Top             =   0
  38.       Width           =   285
  39.    End
  40.    Begin VB.PictureBox picHTML 
  41.       Appearance      =   0  'Flat
  42.       AutoRedraw      =   -1  'True
  43.       BackColor       =   &H80000005&
  44.       BorderStyle     =   0  'None
  45.       CausesValidation=   0   'False
  46.       ClipControls    =   0   'False
  47.       ForeColor       =   &H80000008&
  48.       Height          =   525
  49.       Left            =   0
  50.       ScaleHeight     =   35
  51.       ScaleMode       =   3  'Pixel
  52.       ScaleWidth      =   31
  53.       TabIndex        =   0
  54.       Top             =   0
  55.       Visible         =   0   'False
  56.       Width           =   465
  57.    End
  58. Attribute VB_Name = "HTMLLabel"
  59. Attribute VB_GlobalNameSpace = False
  60. Attribute VB_Creatable = True
  61. Attribute VB_PredeclaredId = False
  62. Attribute VB_Exposed = False
  63. ' UserControl HTMLLabel.
  64. ' Version 0.1.0.
  65. ' A static HTML rendering control.
  66. ' Copyright 
  67.  2001 Woodbury Associates.
  68. Option Explicit
  69. ' Windows API declarations.
  70. Private Const SRCCOPY = &HCC0020
  71. Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, _
  72.                                              ByVal X As Long, ByVal Y As Long, _
  73.                                              ByVal nWidth As Long, ByVal nHeight As Long, _
  74.                                              ByVal hSrcDC As Long, _
  75.                                              ByVal xSrc As Long, ByVal ySrc As Long, _
  76.                                              ByVal dwRop As Long) As Long
  77. ' Private constants.
  78. Private Const mcstrVersion          As String = "0.1.0"
  79. Private Const mcstrDefaultFontName  As String = "Arial"
  80. Private Const mcsngDefaultFontSize  As Single = 10
  81. Private Const mcstrDefaultBackColor As Long = vbButtonFace
  82. Private Const mcstrResIDHandCursor  As String = "HAND_CURSOR"
  83. Private Const mcintMaxTableCols     As Integer = 16
  84. Private Const mcintMaxNestingLevel  As Integer = 16
  85. ' Private enumerations.
  86. ' enumHTMLElementType
  87. ' HTML tag tokens.
  88. Private Enum enumHTMLElementType
  89.     hetContent
  90.     hetUnknown
  91.     hetHEADon
  92.     hetHEADoff
  93.     hetTITLEon
  94.     hetTITLEoff
  95.     hetBODYon
  96.     hetBODYoff
  97.     hetCommenton
  98.     hetCommentoff
  99.     hetSTRONGon
  100.     hetSTRONGoff
  101.     hetEMon
  102.     hetEMoff
  103.     hetUon
  104.     hetUoff
  105.     hetPon
  106.     hetPoff
  107.     hetBR
  108.     hetHR
  109.     hetULon
  110.     hetULoff
  111.     hetOLon
  112.     hetOLoff
  113.     hetLI
  114.     hetTABLEon
  115.     hetTABLEoff
  116.     hetTHEADon
  117.     hetTHEADoff
  118.     hetTBODYon
  119.     hetTBODYoff
  120.     hetTFOOTon
  121.     hetTFOOToff
  122.     hetTRon
  123.     hetTRoff
  124.     hetTDon
  125.     hetTDoff
  126.     hetFONTon
  127.     hetFONToff
  128.     hetAon
  129.     hetAoff
  130.     hetIMG
  131.     hetBLOCKQUOTEon
  132.     hetBLOCKQUOTEoff
  133.     hetHeaderon
  134.     hetHeaderoff
  135.     hetBIGon
  136.     hetBIGoff
  137.     hetSMALLon
  138.     hetSMALLoff
  139.     hetCenteron
  140.     hetCenteroff
  141.     hetSUBon                                    ' Not implemented.
  142.     hetSUBoff                                   ' Not implemented.
  143.     hetSUPon                                    ' Not implemented.
  144.     hetSUPoff                                   ' Not implemented.
  145.     hetFORMon                                   ' Always ignored.
  146.     hetFORMoff                                  ' Always ignored.
  147.     hetSCRIPTon                                 ' Always ignored.
  148.     hetSCRIPToff                                ' Always ignored.
  149.     hetSTYLEon                                  ' Always ignored.
  150.     hetSTYLEoff                                 ' Always ignored.
  151. End Enum
  152. ' Private types.
  153. ' tHTMLElement
  154. ' Represents a single HTML element.
  155. Private Type tHTMLElement
  156.     ' General properties.
  157.     strHTML         As String
  158.     blnIsTag        As Boolean
  159.     hetType         As enumHTMLElementType
  160.     strID           As String
  161.     ' Text words.
  162.     astrWords()     As String
  163.     ' Font attributes.
  164.     strFontName     As String
  165.     sngFontSize     As Single
  166.     lngFontColor    As Long
  167.     ' Anchor attributes.
  168.     strAhref        As String
  169.     lngTop          As Long
  170.     lngLeft         As Long
  171.     lngBottom       As Long
  172.     lngRight        As Long
  173.     lngIndent       As Long
  174.     blnCentre       As Boolean
  175.     ' Image attributes.
  176.     strImgSrc       As String
  177.     strImgAlt       As String
  178.     ' List attributes.
  179.     blnListNumbered As Boolean
  180.     intListNumber   As Integer
  181.     ' Table attributes.
  182.     sngTableWidth   As Single
  183.     lngTableWidth   As Long
  184.     sngCellWidth    As Single
  185.     intCellWidth    As Integer
  186.     intBorderWidth  As Integer
  187.     intCellPadding  As Integer
  188.     intCellSpacing  As Integer
  189.     intColSpan      As Integer
  190.     ' Document hierarchy attributes.
  191.     intChildElements    As Integer
  192.     aintChildElements() As Integer
  193.     intParentElement    As Integer
  194.     intChildIndex       As Integer
  195.     intElementIndex     As Integer
  196. End Type
  197. ' tColumn
  198. ' A single table column.
  199. Private Type tColumn
  200.     lngLeft     As Long
  201.     lngRight    As Long
  202. End Type
  203. ' tTable
  204. ' A table.
  205. Private Type tTable
  206.     blnCentre                   As Boolean
  207.     intBorderWidth              As Integer
  208.     lngTableLeft                As Long
  209.     lngTableTop                 As Long
  210.     lngTableWidth               As Long
  211.     lngTableHeight              As Long
  212.     lngRowTop                   As Long
  213.     lngRowHeight                As Long
  214.     lngCellLeft                 As Long
  215.     lngMarginRight              As Long
  216.     intCol                      As Integer
  217.     audtCol(mcintMaxTableCols)  As tColumn
  218.     intCellPadding              As Integer
  219.     intCellSpacing              As Integer
  220.     intElement                  As Integer
  221. End Type
  222. ' Public events.
  223. Public Event HyperlinkClick(Href As String)
  224. ' Private member variables.
  225. Private mstrDefaultFontName As String
  226. Private msngDefaultFontSize As Single
  227. Private mstrHTML            As String
  228. Private mintElements        As Integer
  229. Private maudtElement()      As tHTMLElement
  230. Private mastrTagAttrName()  As String
  231. Private mastrTagAttrValue() As String
  232. Private mblnEnableScroll    As Boolean
  233. Private mblnEnableAnchors   As Boolean
  234. Private mintAnchors         As Integer
  235. Private maintAnchor()       As Integer
  236. Private mstrAhref           As String
  237. Private mlngTextColor       As Long
  238. Private mlngLinkColor       As Long
  239. ' Public properties.
  240. ' Version
  241. Public Property Get Version() As String
  242.     Version = mcstrVersion
  243. End Property
  244. ' DefaultFontName
  245. Public Property Get DefaultFontName() As String
  246.     DefaultFontName = mstrDefaultFontName
  247. End Property
  248. Public Property Let DefaultFontName(strNewVal As String)
  249.     mstrDefaultFontName = strNewVal
  250. End Property
  251. ' DefaultFontSize
  252. Public Property Get DefaultFontSize() As Single
  253.     DefaultFontSize = msngDefaultFontSize
  254. End Property
  255. Public Property Let DefaultFontSize(sglNewVal As Single)
  256.     msngDefaultFontSize = sglNewVal
  257. End Property
  258. ' BackColor
  259. Public Property Get BackColor() As Long
  260.     BackColor = UserControl.BackColor
  261. End Property
  262. Public Property Let BackColor(lngNewVal As Long)
  263.     UserControl.BackColor = lngNewVal
  264.     picHTML.BackColor = lngNewVal
  265.     picViewPort_Paint
  266. End Property
  267. ' Appearance
  268. Public Property Get Appearance() As Integer
  269.     Appearance = UserControl.Appearance
  270. End Property
  271. Public Property Let Appearance(lngNewVal As Integer)
  272.     UserControl.Appearance = lngNewVal
  273. End Property
  274. ' BorderStyle
  275. Public Property Get BorderStyle() As Integer
  276.     BorderStyle = UserControl.BorderStyle
  277. End Property
  278. Public Property Let BorderStyle(lngNewVal As Integer)
  279.     UserControl.BorderStyle = lngNewVal
  280. End Property
  281. ' DocumentHTML
  282. Public Property Get DocumentHTML() As String
  283.     DocumentHTML = mstrHTML
  284. End Property
  285. Public Property Let DocumentHTML(strNewVal As String)
  286.     picViewPort.MousePointer = vbHourglass
  287.     DoEvents
  288.     mstrHTML = Replace(Replace(strNewVal, Chr(10), " "), Chr(13), " ")
  289.     ' Reset the colour.
  290.     BackColor = mcstrDefaultBackColor
  291.     mlngTextColor = vbBlack
  292.     mlngLinkColor = vbBlue
  293.     mSetDefaultStyle
  294.     ' Replace some common character entities with their character literals.
  295.     mstrHTML = Replace(mstrHTML, "<", "&#" & Format(Asc("<"), "000") & ";")
  296.     mstrHTML = Replace(mstrHTML, ">", "&#" & Format(Asc(">"), "000") & ";")
  297.     mstrHTML = Replace(mstrHTML, """, "&#" & Format(Asc(""""), "000") & ";")
  298.     mstrHTML = Replace(mstrHTML, " ", "&#" & Format(Asc(" "), "000") & ";")
  299.     mstrHTML = Replace(mstrHTML, "©", "©")
  300.     mstrHTML = Replace(mstrHTML, "°", "°")
  301.     mstrHTML = Replace(mstrHTML, "&", "&#" & Format(Asc("&"), "000") & ";")
  302.     mstrHTML = Replace(mstrHTML, "·", "·")
  303.     ' Strip whitespace.
  304.     mstrHTML = Replace(mstrHTML, vbTab, " ")
  305.     mstrHTML = Replace(mstrHTML, vbCrLf, " ")
  306.     mstrHTML = Replace(Replace(Replace(mstrHTML, "  ", " "), "  ", " "), "  ", " ")
  307.     ' Split the HTML into its constituent elements.
  308.     mElementSplit
  309.     ' Parse the elements.
  310.     mParseHTMLElements
  311.     mBuildHierarchy
  312.     ' Refresh the display if we are already visible.
  313.     If UserControl.Parent.Visible Then
  314.         Refresh False
  315.     End If
  316.     picViewPort.MousePointer = vbDefault
  317.     DoEvents
  318. End Property
  319. ' EnableScroll
  320. Public Property Get EnableScroll() As Boolean
  321.     EnableScroll = mblnEnableScroll
  322. End Property
  323. Public Property Let EnableScroll(blnNewVal As Boolean)
  324.     mblnEnableScroll = blnNewVal
  325. End Property
  326. ' EnableAnchors
  327. Public Property Get EnableAnchors() As Boolean
  328.     EnableAnchors = mblnEnableAnchors
  329. End Property
  330. Public Property Let EnableAnchors(blnNewVal As Boolean)
  331.     mblnEnableAnchors = blnNewVal
  332. End Property
  333. ' DocumentTitle
  334. Public Property Get DocumentTitle() As String
  335.     Dim intElem As Integer
  336.     DocumentTitle = "Unknown"
  337.     ' Locate the <TITLE></TITLE> tag within our list of HTML elements.
  338.     If mintElements > 0 Then
  339.         For intElem = 0 To UBound(maudtElement) - 1
  340.             If maudtElement(intElem).hetType = hetTITLEon Then
  341.                 DocumentTitle = mstrDecodeText(maudtElement(intElem + 1).strHTML)
  342.                 Exit For
  343.             End If
  344.         Next intElem
  345.     End If
  346. End Property
  347. ' picHTML_Paint()
  348. ' Repaint the off-screen buffer.
  349. Private Sub picHTML_Paint()
  350.     If UserControl.Ambient.UserMode Then
  351.         If mintElements > 0 Then
  352.             mRenderElements False
  353.         End If
  354.     End If
  355. End Sub
  356. ' picViewPort_Paint()
  357. ' Repaint the viewing window.
  358. Private Sub picViewPort_Paint()
  359.     BitBlt picViewPort.hDC, 0, 0, picViewPort.ScaleWidth, picViewPort.ScaleHeight, _
  360.                         picHTML.hDC, 0, 0, SRCCOPY
  361. End Sub
  362. ' tmrHyperlinkClick_Timer()
  363. ' Fire the "hyperlink clicked" event after a delay which allows the control to complete processing before the event is fired.
  364. Private Sub tmrHyperlinkClick_Timer()
  365.     tmrHyperlinkClick.Enabled = False
  366.     If Len(mstrAhref) > 0 Then
  367.         ' Inform the container that an external target has been requested.
  368.         RaiseEvent HyperlinkClick(mstrAhref)
  369.         mstrAhref = ""
  370.     End If
  371. End Sub
  372. ' Private methods.
  373. ' UserControl_Initialize()
  374. ' Perform default initialisation.
  375. Private Sub UserControl_Initialize()
  376.     mstrDefaultFontName = mcstrDefaultFontName
  377.     msngDefaultFontSize = mcsngDefaultFontSize
  378.     UserControl.BackColor = mcstrDefaultBackColor
  379.     mlngTextColor = vbBlack
  380.     mlngLinkColor = vbBlue
  381.     picViewPort.MouseIcon = LoadResPicture(mcstrResIDHandCursor, vbResCursor)
  382. End Sub
  383. ' UserControl_ReadProperties()
  384. ' Load the properties set at design time for this instance of the control.
  385. Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  386.     UserControl.Appearance = PropBag.ReadProperty("Appearance", 1)
  387.     UserControl.BorderStyle = PropBag.ReadProperty("BorderStyle", 1)
  388.     UserControl.BackColor = PropBag.ReadProperty("BackColor", vbButtonFace)
  389.     picHTML.BackColor = UserControl.BackColor
  390.     mblnEnableAnchors = PropBag.ReadProperty("EnableAnchors", False)
  391.     mblnEnableScroll = PropBag.ReadProperty("EnableScroll", False)
  392.     mstrDefaultFontName = PropBag.ReadProperty("DefaultFontName", "MS Sans Serif")
  393.     msngDefaultFontSize = PropBag.ReadProperty("DefaultFontSize", 10)
  394. End Sub
  395. ' UserControl_WriteProperties()
  396. ' Store the properties set at design time for this instance of the control.
  397. Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  398.     PropBag.WriteProperty "Appearance", UserControl.Appearance
  399.     PropBag.WriteProperty "BorderStyle", UserControl.BorderStyle
  400.     PropBag.WriteProperty "BackColor", UserControl.BackColor
  401.     PropBag.WriteProperty "EnableAnchors", mblnEnableAnchors
  402.     PropBag.WriteProperty "EnableScroll", mblnEnableScroll
  403.     PropBag.WriteProperty "DefaultFontName", mstrDefaultFontName
  404.     PropBag.WriteProperty "DefaultFontSize", msngDefaultFontSize
  405. End Sub
  406. ' UserControl_Resize()
  407. ' Resize event handler.
  408. Private Sub UserControl_Resize()
  409.     If UserControl.Parent.WindowState <> vbMinimized And Height > 360 Then
  410.         ' Position our controls.
  411.         If mblnEnableScroll Then
  412.             vscScroll.Left = Width - vscScroll.Width - IIf(UserControl.Appearance = 1, 60, 30)
  413.             vscScroll.Height = Height - vscScroll.Top - IIf(UserControl.Appearance = 1, 60, 30)
  414.             picHTML.Width = vscScroll.Left - picHTML.Left
  415.             picHTML.Height = vscScroll.Height
  416.             picViewPort.Width = picHTML.Width
  417.             picViewPort.Height = picHTML.Height
  418.             vscScroll.Value = 0
  419.         Else
  420.             picHTML.Width = Width - IIf(UserControl.Appearance = 1, 30, 0)
  421.             picHTML.Height = Height - IIf(UserControl.Appearance = 1, 30, 0)
  422.             picViewPort.Width = picHTML.Width
  423.             picViewPort.Height = picHTML.Height
  424.         End If
  425.     End If
  426. End Sub
  427. ' picViewPort_MouseMove()
  428. ' Show the "hand" cursor if the mouse pointer moves across an anchor.
  429. Private Sub picViewPort_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  430.     Dim blnHit      As Boolean
  431.     Dim intAnchor   As Integer
  432.     On Error Resume Next
  433.     If mblnEnableAnchors Then
  434.         ' Is the mouse pointer curretly over a hyperlink ?
  435.         For intAnchor = 0 To mintAnchors - 1
  436.             If Len(maudtElement(maintAnchor(intAnchor)).strAhref) > 0 Then
  437.                 If maudtElement(maintAnchor(intAnchor)).lngLeft <= X And _
  438.                    maudtElement(maintAnchor(intAnchor)).lngRight >= X And _
  439.                    maudtElement(maintAnchor(intAnchor)).lngBottom - (vscScroll.Value * 10) >= Y And _
  440.                    maudtElement(maintAnchor(intAnchor)).lngTop - (vscScroll.Value * 10) <= Y Then
  441.                     blnHit = True
  442.                     Exit For
  443.                 End If
  444.             End If
  445.         Next intAnchor
  446.         ' Set the cursor depending on whether or not the pointer is over a hyperlink.
  447.         If blnHit Then
  448.             picViewPort.MousePointer = vbCustom
  449.             picViewPort.ToolTipText = maudtElement(maintAnchor(intAnchor)).strAhref
  450.         Else
  451.             picViewPort.MousePointer = vbArrow 'vbDefault
  452.             picViewPort.ToolTipText = ""
  453.         End If
  454.     End If
  455. End Sub
  456. ' picViewPort_MouseUp()
  457. ' Fire the "hyperlink clicked" event if the mouse is clicked on an anchor.
  458. Private Sub picViewPort_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  459.     Dim blnHit      As Boolean
  460.     Dim intAnchor   As Integer
  461.     Dim intTarget   As Integer
  462.     On Error Resume Next
  463.     If mblnEnableAnchors Then
  464.         ' Is the mouse pointer curretly over a hyperlink ?
  465.         For intAnchor = 0 To mintAnchors - 1
  466.             If maudtElement(maintAnchor(intAnchor)).lngLeft <= X And _
  467.                maudtElement(maintAnchor(intAnchor)).lngRight >= X And _
  468.                maudtElement(maintAnchor(intAnchor)).lngBottom - (vscScroll.Value * 10) >= Y And _
  469.                maudtElement(maintAnchor(intAnchor)).lngTop - (vscScroll.Value * 10) <= Y Then
  470.                 blnHit = (Len(maudtElement(maintAnchor(intAnchor)).strAhref) > 0)
  471.                 Exit For
  472.             End If
  473.         Next intAnchor
  474.         If blnHit Then
  475.             ' Scroll to the referenced anchor if the clicked hyperlink refers to an internal
  476.             ' destination anchor.
  477.             If mblnEnableScroll And Left(maudtElement(maintAnchor(intAnchor)).strAhref, 1) = "#" Then
  478.                 For intTarget = 0 To UBound(maudtElement)
  479.                     If maudtElement(intTarget).strID = Mid(maudtElement(maintAnchor(intAnchor)).strAhref, 2) Then
  480.                         If (maudtElement(intTarget).lngTop \ 10) <= vscScroll.Max Then
  481.                             vscScroll.Value = (maudtElement(intTarget).lngTop \ 10)
  482.                         Else
  483.                             vscScroll.Value = vscScroll.Max
  484.                         End If
  485.                     End If
  486.                 Next intTarget
  487.             Else
  488.                 ' Prepare to fire the HyperlinkClick event.
  489.                 mstrAhref = maudtElement(maintAnchor(intAnchor)).strAhref
  490.                 tmrHyperlinkClick.Enabled = True
  491.             End If
  492.         End If
  493.     End If
  494. End Sub
  495. ' picViewPort_KeyDown()
  496. ' Provide keyboard-only scrolling.
  497. Private Sub picViewPort_KeyDown(KeyCode As Integer, Shift As Integer)
  498.     On Error Resume Next
  499.     If mblnEnableScroll Then
  500.         Select Case KeyCode
  501.             Case vbKeyUp
  502.                 If vscScroll.Value > vscScroll.Min Then
  503.                     vscScroll.Value = vscScroll.Value - vscScroll.SmallChange
  504.                 End If
  505.             Case vbKeyDown
  506.                 If vscScroll.Value < vscScroll.Max Then
  507.                     vscScroll.Value = vscScroll.Value + vscScroll.SmallChange
  508.                 End If
  509.             Case vbKeyPageUp
  510.                 If vscScroll.Value > vscScroll.Min Then
  511.                     If vscScroll.Value - vscScroll.LargeChange >= vscScroll.Min Then
  512.                         vscScroll.Value = vscScroll.Value - vscScroll.LargeChange
  513.                     Else
  514.                         vscScroll.Value = vscScroll.Min
  515.                     End If
  516.                 End If
  517.             Case vbKeyPageDown
  518.                 If vscScroll.Value < vscScroll.Max Then
  519.                     If vscScroll.Value + vscScroll.LargeChange <= vscScroll.Max Then
  520.                         vscScroll.Value = vscScroll.Value + vscScroll.LargeChange
  521.                     Else
  522.                         vscScroll.Value = vscScroll.Max
  523.                     End If
  524.                 End If
  525.             Case vbKeyHome
  526.                 If (Shift And vbCtrlMask) > 0 Then
  527.                     vscScroll.Value = vscScroll.Min
  528.                 End If
  529.             Case vbKeyEnd
  530.                 If (Shift And vbCtrlMask) > 0 Then
  531.                     vscScroll.Value = vscScroll.Max
  532.                 End If
  533.             Case Else
  534.         End Select
  535.     End If
  536. End Sub
  537. ' vscScroll_Change()
  538. ' Update the display after a scrollbar change.
  539. Private Sub vscScroll_Change()
  540.     If UserControl.Ambient.UserMode Then
  541.         If mintElements > 0 Then
  542.             mRenderElements False
  543.             On Error Resume Next
  544.             picViewPort_Paint
  545.         End If
  546.     End If
  547. End Sub
  548. ' vscScroll_Scroll()
  549. ' Update the display during drag-and-drop scrolling.
  550. Private Sub vscScroll_Scroll()
  551.     If UserControl.Ambient.UserMode Then
  552.         If mintElements > 0 Then
  553.             mRenderElements False
  554.             picViewPort_Paint
  555.         End If
  556.     End If
  557. End Sub
  558. ' Refresh()
  559. ' Refresh the display.
  560. ' PaintOnly :   When True, indicates that the entire document should be redrawn, otherwise only the current
  561. '               viewable region should be drawn.
  562. Public Sub Refresh(Optional PaintOnly As Boolean = True)
  563.     If UserControl.Ambient.UserMode Then
  564.         picViewPort.MousePointer = vbHourglass
  565.         ' Refresh the display.
  566.         If mintElements > 0 Then
  567.             mRenderElements (Not PaintOnly)
  568.         End If
  569.         ' Re-initialise the scroll bar.
  570.         If mblnEnableScroll Then
  571.             If mintElements > 0 Then
  572.                 vscScroll.Max = (maudtElement(mintElements - 1).lngBottom + 20 - picViewPort.ScaleHeight) \ 10
  573.             Else
  574.                 vscScroll.Max = 0
  575.             End If
  576.             vscScroll.LargeChange = IIf(picViewPort.ScaleHeight \ 10 >= 1, picViewPort.ScaleHeight \ 10, 1)
  577.         
  578.             If vscScroll.Max > 0 Then
  579.                 vscScroll.Enabled = True
  580.                 vscScroll.Value = 0
  581.                 vscScroll.Enabled = True
  582.             Else
  583.                 vscScroll.Max = 0
  584.                 vscScroll.Value = 0
  585.                 vscScroll.Enabled = False
  586.             End If
  587.             vscScroll.Visible = True
  588.         Else
  589.             vscScroll.Visible = False
  590.         End If
  591.         ' Refresh the display.
  592.         picViewPort_Paint
  593.         picViewPort.MousePointer = vbDefault
  594.     End If
  595. End Sub
  596. ' mElementSplit()
  597. ' Split the current HTML into its constituent HTML elements.
  598. Private Sub mElementSplit()
  599.     Dim intStart    As Integer
  600.     Dim intEnd      As Integer
  601.     On Error Resume Next
  602.     mintElements = 0
  603.     Erase maudtElement
  604.     On Error GoTo ErrorHandler
  605.     intStart = 1
  606.     intEnd = 0
  607.     While intEnd < Len(mstrHTML)
  608.         ' Locate the start of the next tag.
  609.         intStart = InStr(intStart, mstrHTML, "<")
  610.         If intStart > 0 Then
  611.             If Mid(mstrHTML, intStart, 4) = "<!--" Then
  612.                 ' Grab everything within the comment.
  613.                 intEnd = InStr(intStart, mstrHTML, "-->") + 2
  614.             Else
  615.                 ' Extract the tag (if one is found).
  616.                 intEnd = InStr(intStart, mstrHTML, ">")
  617.             End If
  618.             If intEnd > 0 Then
  619.                 If Len(Trim(Mid(mstrHTML, intStart, intEnd - intStart + 1))) > 0 Then
  620.                     ReDim Preserve maudtElement(mintElements)
  621.                     maudtElement(mintElements).strHTML = Mid(mstrHTML, intStart, intEnd - intStart + 1)
  622.                     maudtElement(mintElements).intElementIndex = mintElements
  623.                     mintElements = mintElements + 1
  624.                     intEnd = intEnd + 1
  625.                 End If
  626.                 intStart = intEnd
  627.             End If
  628.             ' Extract the content which follows the tag (if there is any).
  629.             intEnd = InStr(intStart, mstrHTML, "<")
  630.             If intEnd > 0 And intEnd - intStart > 0 Then
  631.                 If Len(Trim(Mid(mstrHTML, intStart, intEnd - intStart))) Then
  632.                     ReDim Preserve maudtElement(mintElements)
  633.                     maudtElement(mintElements).strHTML = Mid(mstrHTML, intStart, intEnd - intStart)
  634.                     maudtElement(mintElements).intElementIndex = mintElements
  635.                     mintElements = mintElements + 1
  636.                 End If
  637.                 intStart = intEnd
  638.             ElseIf intEnd = 0 Then
  639.                 ' Pass 1 complete.
  640.                 intEnd = Len(mstrHTML)
  641.             End If
  642.         End If
  643.     Wend
  644. ExitPoint:
  645.     Exit Sub
  646. ErrorHandler:
  647.     Resume ExitPoint
  648. End Sub
  649. ' mblnIsTag()
  650. ' Return True if the specified text is an HTML tag.
  651. Private Function mblnIsTag(strText As String) As Boolean
  652.     mblnIsTag = (Left(strText, 1) = "<" And Right(strText, 1) = ">")
  653. End Function
  654. ' mstrTagID()
  655. ' Extract and return the HTML tag identifier from the specified string.
  656. Public Function mstrTagID(strTag As String) As String
  657.     Dim intEnd      As Integer
  658.     Dim strRetVal   As String
  659.     intEnd = InStr(strTag, " ")
  660.     If intEnd > 0 Then
  661.         strRetVal = Mid(strTag, 2, intEnd - 1)
  662.     Else
  663.         strRetVal = Mid(Trim(strTag), 2, Len(Trim(strTag)) - 2)
  664.     End If
  665.     mstrTagID = UCase(Trim(strRetVal))
  666. End Function
  667. ' mintExtractTagAttributes()
  668. ' Extract the attribute names and values from the tag contained in the specified string.
  669. Public Function mintExtractTagAttributes(strTag As String) As Integer
  670.     Dim intRetVal   As Integer
  671.     Dim intStart    As Integer
  672.     Dim intEnd      As Integer
  673.     Dim strDelim    As String
  674.     Erase mastrTagAttrName
  675.     Erase mastrTagAttrValue
  676.     intStart = InStr(strTag, " ")
  677.     If intStart > 0 Then
  678.     While InStr(intStart, strTag, "=") > 0
  679.         ' Extract the next attribute name.
  680.         intEnd = InStr(intStart + 1, strTag, "=")
  681.         ReDim Preserve mastrTagAttrName(intRetVal)
  682.         mastrTagAttrName(intRetVal) = Replace(Trim(UCase(Mid(strTag, intStart, intEnd - intStart))), vbTab, "")
  683.         ' Ascertain the value delimiter ("'", """ or " ").
  684.         strDelim = " "
  685.         intStart = intEnd + 1
  686.         While Mid(strTag, intStart, 1) = " "
  687.             intStart = intStart + 1
  688.         Wend
  689.         If Mid(strTag, intStart, 1) = "'" Or Mid(strTag, intStart, 1) = """" Or Mid(strTag, intStart, 1) = " " Then
  690.             strDelim = Mid(strTag, intStart, 1)
  691.         End If
  692.         ' Locate the end delimiter.
  693.         If InStr(intStart + 1, strTag, strDelim) > 0 Then
  694.             intEnd = InStr(intStart + 1, strTag, strDelim)
  695.         Else
  696.             intEnd = Len(strTag)
  697.         End If
  698.         ' Extract the attribute value.
  699.         ReDim Preserve mastrTagAttrValue(intRetVal)
  700.         mastrTagAttrValue(intRetVal) = Trim(Mid(strTag, intStart, intEnd - intStart))
  701.         If Left(mastrTagAttrValue(intRetVal), 1) = strDelim Then
  702.             mastrTagAttrValue(intRetVal) = Mid(mastrTagAttrValue(intRetVal), 2)
  703.         End If
  704.         intStart = intEnd + 1
  705.         intRetVal = intRetVal + 1
  706.     Wend
  707.     End If
  708.     mintExtractTagAttributes = intRetVal
  709. End Function
  710. ' mSetDefaultStyle()
  711. ' Reset the PictureBox's style using the current defaults.
  712. Private Sub mSetDefaultStyle()
  713.     picHTML.Font.Name = mstrDefaultFontName
  714.     picHTML.Font.Size = msngDefaultFontSize
  715.     picHTML.ForeColor = mlngTextColor
  716.     picHTML.Font.Bold = False
  717.     picHTML.Font.Italic = False
  718.     picHTML.Font.Underline = False
  719. End Sub
  720. ' mstrDecodeText()
  721. ' Decode the specified HTML-encoded text.
  722. Private Function mstrDecodeText(strText) As String
  723.     Dim intPos      As Integer
  724.     Dim intChar     As Integer
  725.     Dim strRetVal   As String
  726.     If InStr(strText, "&#") > 0 Then
  727.         intPos = 1
  728.         While intPos <= Len(strText)
  729.             If Mid(strText, intPos, 2) = "&#" And InStr(intPos, strText, ";") > 0 Then
  730.                 ' Translate the character literal.
  731.                 intPos = intPos + 2
  732.                 intChar = 0
  733.                 While IsNumeric(Mid(strText, intPos, 1))
  734.                     intChar = (intChar * 10) + CInt(Mid(strText, intPos, 1))
  735.                     intPos = intPos + 1
  736.                 Wend
  737.                 If Len(CStr(intChar)) < 4 Then
  738.                     strRetVal = strRetVal & Chr(intChar)
  739.                 End If
  740.                 intPos = intPos + 1
  741.             Else
  742.                 strRetVal = strRetVal & Mid(strText, intPos, 1)
  743.                 intPos = intPos + 1
  744.             End If
  745.         Wend
  746.     Else
  747.         strRetVal = strText
  748.     End If
  749.     mstrDecodeText = Replace(Replace(Replace(strRetVal, vbCrLf, " "), Chr(10), " "), vbTab, " ")
  750. End Function
  751. ' mParseHTMLElement()
  752. ' Parse the HTML element contained in the specified tHTMLElement structure.
  753. Private Sub mParseHTMLElement(udtElem As tHTMLElement)
  754.     Dim intAttr     As Integer
  755.     Dim strValue    As String
  756.     On Error GoTo ErrorHandler
  757.     If mblnIsTag(udtElem.strHTML) Then
  758.         ' Store the tag's token and attributes.
  759.         udtElem.blnIsTag = True
  760.         Select Case mstrTagID(udtElem.strHTML)
  761.             Case "HEAD"
  762.                 udtElem.hetType = hetHEADon
  763.             Case "/HEAD"
  764.                 udtElem.hetType = hetHEADoff
  765.             Case "TITLE"
  766.                 udtElem.hetType = hetTITLEon
  767.             Case "/TITLE"
  768.                 udtElem.hetType = hetTITLEoff
  769.             Case "BODY", "NOFRAMES"
  770.                 udtElem.hetType = hetBODYon
  771.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  772.                     For intAttr = 0 To UBound(mastrTagAttrName)
  773.                         Select Case mastrTagAttrName(intAttr)
  774.                             Case "BGCOLOR"
  775.                                 strValue = Replace(mastrTagAttrValue(intAttr), "#", "")
  776.                                 If IsNumeric("&H" & strValue) Then
  777.                                     BackColor = RGB(CLng("&H" & Left(strValue, 2)), _
  778.                                                            CLng("&H" & Mid(strValue, 3, 2)), _
  779.                                                            CLng("&H" & Right(strValue, 2)))
  780.                                 Else
  781.                                     BackColor = mlngTranslateHTMLColour(mastrTagAttrValue(intAttr))
  782.                                 End If
  783.                             Case "TEXT"
  784.                                 strValue = Replace(mastrTagAttrValue(intAttr), "#", "")
  785.                                 If IsNumeric("&H" & strValue) Then
  786.                                     mlngTextColor = RGB(CLng("&H" & Left(strValue, 2)), _
  787.                                                            CLng("&H" & Mid(strValue, 3, 2)), _
  788.                                                            CLng("&H" & Right(strValue, 2)))
  789.                                 Else
  790.                                     mlngTextColor = mlngTranslateHTMLColour(mastrTagAttrValue(intAttr))
  791.                                 End If
  792.                             Case "LINK"
  793.                                 strValue = Replace(mastrTagAttrValue(intAttr), "#", "")
  794.                                 If IsNumeric("&H" & strValue) Then
  795.                                     mlngLinkColor = RGB(CLng("&H" & Left(strValue, 2)), _
  796.                                                            CLng("&H" & Mid(strValue, 3, 2)), _
  797.                                                            CLng("&H" & Right(strValue, 2)))
  798.                                 Else
  799.                                     mlngLinkColor = mlngTranslateHTMLColour(mastrTagAttrValue(intAttr))
  800.                                 End If
  801.                             Case Else
  802.                         End Select
  803.                     Next intAttr
  804.                 End If
  805.             Case "/BODY", "/NOFRAMES"
  806.                 udtElem.hetType = hetBODYoff
  807.             Case "!--"
  808.                 udtElem.hetType = hetCommenton
  809.             Case "--"
  810.                 udtElem.hetType = hetCommentoff
  811.             Case "STRONG", "B"
  812.                 udtElem.hetType = hetSTRONGon
  813.             Case "/STRONG", "/B"
  814.                 udtElem.hetType = hetSTRONGoff
  815.             Case "EM", "I"
  816.                 udtElem.hetType = hetEMon
  817.             Case "/EM", "/I"
  818.                 udtElem.hetType = hetEMoff
  819.             Case "U"
  820.                 udtElem.hetType = hetUon
  821.             Case "/U"
  822.                 udtElem.hetType = hetUoff
  823.             Case "P"
  824.                 udtElem.hetType = hetPon
  825.             Case "/P"
  826.                 udtElem.hetType = hetPoff
  827.             Case "BR"
  828.                 udtElem.hetType = hetBR
  829.             Case "HR"
  830.                 udtElem.hetType = hetHR
  831.             Case "UL"
  832.                 udtElem.hetType = hetULon
  833.             Case "/UL"
  834.                 udtElem.hetType = hetULoff
  835.             Case "OL"
  836.                 udtElem.hetType = hetOLon
  837.             Case "/OL"
  838.                 udtElem.hetType = hetOLoff
  839.             Case "LI"
  840.                 udtElem.hetType = hetLI
  841.             Case "BLOCKQUOTE"
  842.                 udtElem.hetType = hetBLOCKQUOTEon
  843.             Case "/BLOCKQUOTE"
  844.                 udtElem.hetType = hetBLOCKQUOTEoff
  845.             Case "TABLE"
  846.                 udtElem.hetType = hetTABLEon
  847.                 udtElem.intCellSpacing = 2
  848.                 udtElem.intCellPadding = 2
  849.                 udtElem.sngTableWidth = 1
  850.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  851.                     For intAttr = 0 To UBound(mastrTagAttrName)
  852.                         Select Case mastrTagAttrName(intAttr)
  853.                             Case "WIDTH"
  854.                                 If InStr(mastrTagAttrValue(intAttr), "%") > 0 Then
  855.                                     udtElem.sngTableWidth = Replace(mastrTagAttrValue(intAttr), "%", "") / 100
  856.                                 Else
  857.                                     udtElem.sngTableWidth = mastrTagAttrValue(intAttr)
  858.                                 End If
  859.                             Case "BORDER"
  860.                                 udtElem.intBorderWidth = mastrTagAttrValue(intAttr)
  861.                             Case "CELLPADDING"
  862.                                 udtElem.intCellPadding = mastrTagAttrValue(intAttr)
  863.                             Case "CELLSPACING"
  864.                                 udtElem.intCellSpacing = mastrTagAttrValue(intAttr)
  865.                             Case "ALIGN"
  866.                                 If UCase(mastrTagAttrValue(intAttr)) = "CENTER" Then
  867.                                     udtElem.blnCentre = True
  868.                                 End If
  869.                             Case Else
  870.                         End Select
  871.                     Next intAttr
  872.                 End If
  873.             Case "/TABLE"
  874.                 udtElem.hetType = hetTABLEoff
  875.             Case "THEAD"
  876.                 udtElem.hetType = hetTHEADon
  877.             Case "/THEAD"
  878.                 udtElem.hetType = hetTHEADoff
  879.             Case "TBODY"
  880.                 udtElem.hetType = hetTBODYon
  881.             Case "/TBODY"
  882.                 udtElem.hetType = hetTBODYoff
  883.             Case "TFOOT"
  884.                 udtElem.hetType = hetTFOOTon
  885.             Case "/TFOOT"
  886.                 udtElem.hetType = hetTFOOToff
  887.             Case "TR"
  888.                 udtElem.hetType = hetTRon
  889.             Case "/TR"
  890.                 udtElem.hetType = hetTRoff
  891.             Case "TD", "TH"
  892.                 udtElem.hetType = hetTDon
  893.                 udtElem.intColSpan = 1
  894.                 udtElem.sngCellWidth = 1
  895.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  896.                     For intAttr = 0 To UBound(mastrTagAttrName)
  897.                         Select Case mastrTagAttrName(intAttr)
  898.                             Case "WIDTH"
  899.                                 If InStr(mastrTagAttrValue(intAttr), "%") > 0 Then
  900.                                     udtElem.sngCellWidth = Replace(mastrTagAttrValue(intAttr), "%", "") / 100
  901.                                 Else
  902.                                     udtElem.sngCellWidth = Replace(mastrTagAttrValue(intAttr), "px", "")
  903.                                 End If
  904.                             Case "COLSPAN"
  905.                                 udtElem.intColSpan = mastrTagAttrValue(intAttr)
  906.                             Case "ALIGN"
  907.                                 If UCase(mastrTagAttrValue(intAttr)) = "CENTER" Then
  908.                                     udtElem.blnCentre = True
  909.                                 End If
  910.                             Case Else
  911.                         End Select
  912.                     Next intAttr
  913.                 End If
  914.             Case "/TD", "/TH"
  915.                 udtElem.hetType = hetTDoff
  916.             Case "FONT"
  917.                 udtElem.hetType = hetFONTon
  918.                 udtElem.strFontName = mstrDefaultFontName
  919.                 udtElem.lngFontColor = mlngTextColor
  920.                 udtElem.sngFontSize = msngDefaultFontSize
  921.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  922.                     For intAttr = 0 To UBound(mastrTagAttrName)
  923.                         Select Case mastrTagAttrName(intAttr)
  924.                             Case "FACE"
  925.                                 If InStr(mastrTagAttrValue(intAttr), ",") > 1 Then
  926.                                     udtElem.strFontName = Left(mastrTagAttrValue(intAttr), InStr(mastrTagAttrValue(intAttr), ",") - 1)
  927.                                 Else
  928.                                     udtElem.strFontName = mastrTagAttrValue(intAttr)
  929.                                 End If
  930.                             Case "COLOR"
  931.                                 strValue = Replace(mastrTagAttrValue(intAttr), "#", "")
  932.                                 If IsNumeric("&H" & strValue) Then
  933.                                     udtElem.lngFontColor = RGB(CLng("&H" & Left(strValue, 2)), _
  934.                                                            CLng("&H" & Mid(strValue, 3, 2)), _
  935.                                                            CLng("&H" & Right(strValue, 2)))
  936.                                 Else
  937.                                     udtElem.lngFontColor = mlngTranslateHTMLColour(mastrTagAttrValue(intAttr))
  938.                                 End If
  939.                             Case "SIZE"
  940.                                 If IsNumeric(mastrTagAttrValue(intAttr)) Then
  941.                                     If Left(mastrTagAttrValue(intAttr), 1) = "+" Or _
  942.                                        Left(mastrTagAttrValue(intAttr), 1) = "-" Then
  943.                                         udtElem.sngFontSize = msngDefaultFontSize + (1.2 * CSng(mastrTagAttrValue(intAttr)))
  944.                                     Else
  945.                                         udtElem.sngFontSize = msngDefaultFontSize + (1.2 * (CSng(mastrTagAttrValue(intAttr) - 3)))
  946.                                     End If
  947.                                 End If
  948.                             Case Else
  949.                         End Select
  950.                     Next intAttr
  951.                 End If
  952.             Case "/FONT"
  953.                 udtElem.hetType = hetFONToff
  954.             Case "H1", "H2", "H3", "H4", "H5", "H6"
  955.                 udtElem.hetType = hetHeaderon
  956.                 udtElem.sngFontSize = msngDefaultFontSize + (1.2 * (7 - CSng(Mid(mstrTagID(udtElem.strHTML), 2, 1))))
  957.             Case "/H1", "/H2", "/H3", "/H4", "/H5", "/H6"
  958.                 udtElem.hetType = hetHeaderoff
  959.             Case "BIG"
  960.                 udtElem.hetType = hetBIGon
  961.                 udtElem.sngFontSize = msngDefaultFontSize + 1
  962.             Case "/BIG"
  963.                 udtElem.hetType = hetBIGoff
  964.             Case "SMALL"
  965.                 udtElem.hetType = hetSMALLon
  966.                 udtElem.sngFontSize = msngDefaultFontSize - 1
  967.             Case "/SMALL"
  968.                 udtElem.hetType = hetSMALLoff
  969.             Case "SUP"
  970.                 udtElem.hetType = hetSUPon
  971.             Case "/SUP"
  972.                 udtElem.hetType = hetSUPoff
  973.             Case "SUB"
  974.                 udtElem.hetType = hetSUBon
  975.             Case "/SUB"
  976.                 udtElem.hetType = hetSUBoff
  977.             Case "A"
  978.                 udtElem.hetType = hetAon
  979.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  980.                     For intAttr = 0 To UBound(mastrTagAttrName)
  981.                         Select Case mastrTagAttrName(intAttr)
  982.                             Case "HREF"
  983.                                 udtElem.strAhref = mstrDecodeText(mastrTagAttrValue(intAttr))
  984.                             Case "ID", "NAME"
  985.                                 udtElem.strID = mastrTagAttrValue(intAttr)
  986.                             Case Else
  987.                         End Select
  988.                     Next intAttr
  989.                 End If
  990.                 udtElem.lngTop = -1
  991.                 udtElem.lngLeft = -1
  992.                 udtElem.lngBottom = -1
  993.                 udtElem.lngRight = -1
  994.             Case "/A"
  995.                 udtElem.hetType = hetAoff
  996.             Case "IMG"
  997.                 udtElem.hetType = hetIMG
  998.                 If mintExtractTagAttributes(udtElem.strHTML) > 0 Then
  999.                     For intAttr = 0 To UBound(mastrTagAttrName)
  1000.                         Select Case mastrTagAttrName(intAttr)
  1001.                             Case "SRC"
  1002.                                 udtElem.strImgSrc = mstrDecodeText(mastrTagAttrValue(intAttr))
  1003.                             Case "ALT"
  1004.                                 udtElem.strImgAlt = mstrDecodeText(mastrTagAttrValue(intAttr))
  1005.                             Case Else
  1006.                         End Select
  1007.                     Next intAttr
  1008.                 End If
  1009.             Case "CENTER"
  1010.                 udtElem.hetType = hetCenteron
  1011.             Case "/CENTER"
  1012.                 udtElem.hetType = hetCenteroff
  1013.             Case "FORM"
  1014.                 udtElem.hetType = hetFORMon
  1015.             Case "/FORM"
  1016.                 udtElem.hetType = hetFORMoff
  1017.             Case "SCRIPT"
  1018.                 udtElem.hetType = hetSCRIPTon
  1019.             Case "/SCRIPT"
  1020.                 udtElem.hetType = hetSCRIPToff
  1021.             Case "STYLE"
  1022.                 udtElem.hetType = hetSTYLEon
  1023.             Case "/STYLE"
  1024.                 udtElem.hetType = hetSTYLEoff
  1025.             Case Else
  1026.                 udtElem.hetType = hetUnknown
  1027.         End Select
  1028.     Else
  1029.         udtElem.hetType = hetContent
  1030.         ' Split the text content into individual words.
  1031.         If InStr(mstrDecodeText(udtElem.strHTML), " ") > 0 Then
  1032.             udtElem.astrWords = Split(mstrDecodeText(udtElem.strHTML), " ")
  1033.         Else
  1034.             ReDim udtElem.astrWords(0)
  1035.             udtElem.astrWords(0) = mstrDecodeText(udtElem.strHTML)
  1036.         End If
  1037.     End If
  1038. ExitPoint:
  1039.     Exit Sub
  1040. ErrorHandler:
  1041.     Debug.Print "Error (" & Err.Number & ") " & Err.Description
  1042.     Resume ExitPoint
  1043. End Sub
  1044. ' mParseHTMLElements()
  1045. ' Parse the entire set of HTML elements.
  1046. Private Sub mParseHTMLElements()
  1047.     Dim intElem As Integer
  1048.     Erase maintAnchor
  1049.     mintAnchors = 0
  1050.     For intElem = 0 To mintElements - 1
  1051.         ' Parse the element.
  1052.         mParseHTMLElement maudtElement(intElem)
  1053.         ' Add any anchors to the anchros array.
  1054.         If mblnEnableAnchors And maudtElement(intElem).hetType = hetAon Then
  1055.             ReDim Preserve maintAnchor(mintAnchors)
  1056.             maintAnchor(mintAnchors) = intElem
  1057.             mintAnchors = mintAnchors + 1
  1058.         End If
  1059.     Next intElem
  1060. End Sub
  1061. ' mRenderElements()
  1062. ' Render the entire set of current HTML elements into our PictureBox.
  1063. ' blnLayoutChanged  :   When True, indicates that the control's size has changed and that the document's
  1064. '                       element's layouts must be re-calculated.
  1065. Private Sub mRenderElements(blnLayoutChanged As Boolean)
  1066.     Const clngPadding           As Long = 4
  1067.     Const clngListIndent        As Long = 20
  1068.     Dim blnCentre                           As Boolean
  1069.     Dim blnIgnore                           As Boolean
  1070.     Dim blnStartUnderline                   As Boolean
  1071.     Dim blnSpacerInserted                   As Boolean
  1072.     Dim blnInTable                          As Boolean
  1073.     Dim intElem                             As Integer
  1074.     Dim intWord                             As Integer
  1075.     Dim intNestingLevel                     As Integer
  1076.     Dim aintNumber(mcintMaxNestingLevel, 1) As Integer
  1077.     Dim intLinkElement                      As Integer
  1078.     Dim intTableNestLevel                   As Integer
  1079.     Dim lngX                                As Long
  1080.     Dim lngY                                As Long
  1081.     Dim lngIndent                           As Long
  1082.     Dim lngLastIndent                       As Long
  1083.     Dim lngScrollOffset                     As Long
  1084.     Dim lngLineHeight                       As Long
  1085.     Dim lngIndentStep                       As Long
  1086.     Dim lngXExtent                          As Long
  1087.     Dim lngMarginLeft                       As Long
  1088.     Dim lngMarginRight                      As Long
  1089.     Dim audtTable(mcintMaxNestingLevel - 1) As tTable
  1090.     Dim sngLastFontSize                     As Single
  1091.     Dim strValue                            As String
  1092.     Dim sngCellWidth                        As Single
  1093.     On Error GoTo ErrorHandler
  1094.     ' Initialise.
  1095.     picHTML.Cls
  1096.     mSetDefaultStyle
  1097.     sngLastFontSize = msngDefaultFontSize
  1098.     lngLineHeight = picHTML.TextHeight("X") + clngPadding
  1099.     lngIndentStep = picHTML.TextWidth("W") * 2
  1100.     If mblnEnableScroll And Not blnLayoutChanged Then
  1101.         lngScrollOffset = vscScroll.Value * 10
  1102.     End If
  1103.     lngMarginLeft = clngPadding
  1104.     lngMarginRight = picHTML.ScaleWidth
  1105.     lngX = lngMarginLeft
  1106.     lngY = -lngScrollOffset
  1107.     lngIndent = 0
  1108.     lngLastIndent = 0
  1109.     ' Ignore everything up to the <BODY> tag.
  1110.     Do
  1111.         intElem = intElem + 1
  1112.         If intElem = mintElements Then
  1113.             Exit Do
  1114.         End If
  1115.     Loop While maudtElement(intElem).hetType <> hetBODYon
  1116.     ' Don't draw anything that can't be seen.
  1117.     If (Not blnLayoutChanged) And intElem < mintElements Then
  1118.         Do While maudtElement(intElem).lngBottom < lngScrollOffset - (lngLineHeight * 0)
  1119.             Select Case maudtElement(intElem).hetType
  1120.                 Case hetFONTon
  1121.                     On Error Resume Next
  1122.                     picHTML.FontName = maudtElement(intElem).strFontName
  1123.                     picHTML.FontSize = maudtElement(intElem).sngFontSize
  1124.                     picHTML.ForeColor = maudtElement(intElem).lngFontColor
  1125.                     sngLastFontSize = maudtElement(intElem).sngFontSize
  1126.                     lngLineHeight = picHTML.TextHeight("X") + clngPadding
  1127.                     lngIndentStep = picHTML.TextWidth("W") * 2
  1128.                 Case hetFONToff
  1129.                     mSetDefaultStyle
  1130.                     sngLastFontSize = msngDefaultFontSize
  1131.                 Case Else
  1132.             End Select
  1133.             intElem = intElem + 1
  1134.             If intElem > mintElements Then
  1135.                 Exit Do
  1136.             End If
  1137.         Loop
  1138.         lngX = maudtElement(intElem).lngLeft
  1139.         lngIndent = maudtElement(intElem).lngLeft - clngPadding
  1140.         lngY = maudtElement(intElem).lngTop - lngScrollOffset
  1141.     End If
  1142.     ' Render the HTML elements.
  1143.     Do While intElem < mintElements
  1144.         If blnLayoutChanged Then
  1145.             maudtElement(intElem).lngTop = lngY
  1146.             maudtElement(intElem).lngIndent = 0
  1147.             maudtElement(intElem).lngLeft = lngX
  1148.             maudtElement(intElem).blnCentre = blnCentre Or maudtElement(intElem).blnCentre
  1149.         ElseIf lngY > picHTML.ScaleHeight And Not blnInTable Then
  1150.             Exit Do
  1151.         Else
  1152.             lngY = maudtElement(intElem).lngTop - lngScrollOffset
  1153.             lngX = maudtElement(intElem).lngLeft
  1154.             picHTML.CurrentX = lngX
  1155.         End If
  1156.         If maudtElement(intElem).blnIsTag Then
  1157.             ' Update the prevailing mark-up style.
  1158.             Select Case maudtElement(intElem).hetType
  1159.                 Case hetCommenton
  1160.                     ' Ignore comments.
  1161.                 Case hetFORMon, hetSCRIPTon, hetSTYLEon
  1162.                     blnIgnore = True
  1163.                 Case hetFORMoff, hetSCRIPToff, hetSTYLEoff
  1164.                     blnIgnore = False
  1165.                 Case hetSTRONGon
  1166.                     picHTML.Font.Bold = True
  1167.                 Case hetSTRONGoff
  1168.                     picHTML.Font.Bold = False
  1169.                 Case hetEMon
  1170.                     picHTML.Font.Italic = True
  1171.                 Case hetEMoff
  1172.                     picHTML.Font.Italic = False
  1173.                 Case hetUon
  1174.                     picHTML.Font.Underline = True
  1175.                 Case hetUoff
  1176.                     picHTML.Font.Underline = False
  1177.                 Case hetPon
  1178.                     If blnLayoutChanged Then
  1179.                         lngX = lngMarginLeft + lngIndent
  1180.                         lngY = lngY + lngLineHeight
  1181.                         lngLastIndent = lngX - lngMarginLeft
  1182.                         maudtElement(intElem).lngIndent = lngX - lngMarginLeft
  1183.                     End If
  1184.                 Case hetPoff
  1185.                     If blnLayoutChanged Then
  1186.                         lngX = lngMarginLeft + lngIndent
  1187.                         lngLastIndent = lngX - lngMarginLeft
  1188.                         maudtElement(intElem).lngIndent = lngX - lngMarginLeft
  1189.                         If Not blnSpacerInserted Then
  1190.                             lngY = lngY + lngLineHeight
  1191.                             blnSpacerInserted = True
  1192.                         Else
  1193.                             blnSpacerInserted = False
  1194.                         End If
  1195.                     End If
  1196.                 Case hetBR
  1197.                     If blnLayoutChanged Then
  1198.                         lngX = lngMarginLeft + lngIndent
  1199.                         lngY = lngY + lngLineHeight
  1200.                         lngLastIndent = lngX - lngMarginLeft
  1201.                         maudtElement(intElem).lngIndent = lngX - lngMarginLeft
  1202.                         blnSpacerInserted = False
  1203.                     End If
  1204.                 Case hetHR
  1205.                     If blnLayoutChanged Then
  1206.                         lngX = lngMarginLeft
  1207.                         maudtElement(intElem).lngTop = lngY
  1208.                     End If
  1209.                     picHTML.Line (lngMarginLeft, lngY)-(lngMarginRight - clngPadding, lngY)
  1210.                     lngY = lngY + clngPadding + 1 'lngLineHeight
  1211.                 Case hetULon
  1212.                     If blnLayoutChanged Then
  1213.                         intNestingLevel = intNestingLevel + 1
  1214.                         aintNumber(intNestingLevel, 0) = False
  1215.                         lngIndent = lngIndent + lngIndentStep
  1216.                         lngLastIndent = lngIndent + lngIndentStep
  1217.                         maudtElement(intElem).lngIndent = lngLastIndent
  1218.                         If intNestingLevel = 1 And Not blnSpacerInserted Then
  1219.                             lngY = lngY + lngLineHeight
  1220.                             blnSpacerInserted = True
  1221.                         Else
  1222.                             blnSpacerInserted = False
  1223.                         End If
  1224.                     End If
  1225.                 Case hetULoff
  1226.                     If blnLayoutChanged Then
  1227.                         aintNumber(intNestingLevel, 0) = False
  1228.                         intNestingLevel = intNestingLevel - 1
  1229.                         lngIndent = IIf(lngIndent - lngIndentStep < 0, 0, lngIndent - lngIndentStep)
  1230.                         lngLastIndent = lngIndent
  1231.                         maudtElement(intElem).lngIndent = lngIndent
  1232.                         If intNestingLevel = 0 And Not blnSpacerInserted Then
  1233.                             lngY = lngY + lngLineHeight
  1234.                             blnSpacerInserted = True
  1235.                         Else
  1236.                             blnSpacerInserted = False
  1237.                         End If
  1238.                     End If
  1239.                 Case hetOLon
  1240.                     If blnLayoutChanged Then
  1241.                         intNestingLevel = intNestingLevel + 1
  1242.                         aintNumber(intNestingLevel, 0) = True
  1243.                         aintNumber(intNestingLevel, 1) = 0
  1244.                         lngIndent = lngIndent + lngIndentStep
  1245.                         lngLastIndent = lngIndent + lngIndentStep
  1246.                         maudtElement(intElem).lngIndent = lngLastIndent
  1247.                         If intNestingLevel = 1 And Not blnSpacerInserted Then
  1248.                             lngY = lngY + lngLineHeight
  1249.                             blnSpacerInserted = True
  1250.                         Else
  1251.                             blnSpacerInserted = False
  1252.                         End If
  1253.                     End If
  1254.                 Case hetOLoff
  1255.                     If blnLayoutChanged Then
  1256.                         aintNumber(intNestingLevel, 0) = False
  1257.                         intNestingLevel = intNestingLevel - 1
  1258.                         lngIndent = IIf(lngIndent - lngIndentStep < 0, 0, lngIndent - lngIndentStep)
  1259.                         lngLastIndent = lngIndent
  1260.                         maudtElement(intElem).lngIndent = lngIndent
  1261.                         If intNestingLevel = 0 And Not blnSpacerInserted Then
  1262.                             lngY = lngY + lngLineHeight
  1263.                             blnSpacerInserted = True
  1264.                         Else
  1265.                             blnSpacerInserted = False
  1266.                         End If
  1267.                     End If
  1268.                 Case hetLI
  1269.                     If blnLayoutChanged Then
  1270.                         lngX = lngMarginLeft + lngIndent
  1271.                         lngY = lngY + lngLineHeight
  1272.                         maudtElement(intElem).lngTop = lngY
  1273.                         maudtElement(intElem).lngIndent = lngIndent
  1274.                         If aintNumber(intNestingLevel, 0) Then
  1275.                             aintNumber(intNestingLevel, 1) = aintNumber(intNestingLevel, 1) + 1
  1276.                             If blnLayoutChanged Then
  1277.                                 picHTML.CurrentX = lngX
  1278.                                 picHTML.CurrentY = lngY
  1279.                                 maudtElement(intElem).blnListNumbered = True
  1280.                                 maudtElement(intElem).intListNumber = aintNumber(intNestingLevel, 1)
  1281.                             End If
  1282.                         End If
  1283.                     End If
  1284.                     picHTML.CurrentY = lngY
  1285.                     If maudtElement(intElem).blnListNumbered Then
  1286.                         ' Insert the list element's number.
  1287.                         picHTML.CurrentX = lngMarginLeft + maudtElement(intElem).lngIndent
  1288.                         picHTML.Print maudtElement(intElem).intListNumber & ". ";
  1289.                         lngX = lngX + picHTML.TextWidth("W" & ". ")
  1290.                     Else
  1291.                         ' Insert the list element's bullet.
  1292.                         picHTML.CurrentX = lngMarginLeft + maudtElement(intElem).lngIndent
  1293.                         picHTML.Print Chr(149) & "  ";
  1294.                         lngX = lngX + picHTML.TextWidth(Chr(149) & "  ")
  1295.                     End If
  1296.                     lngLastIndent = lngX
  1297.                 Case hetTABLEon
  1298.                     ' Move to a new line if we're not already inside a table.
  1299.                     If Not blnInTable Then
  1300.                         lngY = lngY + lngLineHeight
  1301.                     End If
  1302.                     blnInTable = True
  1303.                     ' Calculate the table's width
  1304.                     If maudtElement(intElem).sngTableWidth <= 1 Then
  1305.                         audtTable(intTableNestLevel).lngTableWidth = _
  1306.                                 (lngMarginRight - (clngPadding * 2) - lngMarginLeft - _
  1307.                                 maudtElement(intElem).intBorderWidth * 2 - _
  1308.                                 maudtElement(intElem).intCellSpacing) * _
  1309.                                 maudtElement(intElem).sngTableWidth
  1310.                     Else
  1311.                         audtTable(intTableNestLevel).lngTableWidth = maudtElement(intElem).sngTableWidth
  1312.                     End If
  1313.                     ' Layout the table.
  1314.                     maudtElement(intElem).lngTableWidth = audtTable(intTableNestLevel).lngTableWidth
  1315.                     mLayoutTable maudtElement(intElem)
  1316.                     ' Initialise the table.
  1317.                     audtTable(intTableNestLevel).lngTableTop = lngY
  1318.                     audtTable(intTableNestLevel).lngRowTop = lngY + maudtElement(intElem).intBorderWidth
  1319.                     audtTable(intTableNestLevel).lngRowHeight = 0
  1320.                     audtTable(intTableNestLevel).intBorderWidth = maudtElement(intElem).intBorderWidth
  1321.                     audtTable(intTableNestLevel).lngTableHeight = maudtElement(intElem).intBorderWidth
  1322.                     audtTable(intTableNestLevel).intCellSpacing = maudtElement(intElem).intCellSpacing
  1323.                     audtTable(intTableNestLevel).intCellPadding = maudtElement(intElem).intCellPadding
  1324.                     audtTable(intTableNestLevel).intElement = intElem
  1325.                     ' Set the table's left edge.
  1326.                     If maudtElement(intElem).blnCentre Then
  1327.                         audtTable(intTableNestLevel).lngTableLeft = _
  1328.                             ((lngMarginRight - lngMarginLeft) - _
  1329.                             audtTable(intTableNestLevel).lngTableWidth) \ 2 + lngMarginLeft
  1330.                         If audtTable(intTableNestLevel).lngTableLeft < lngMarginLeft Then
  1331.                             If intTableNestLevel = 0 Then
  1332.                                 audtTable(intTableNestLevel).lngTableLeft = lngMarginLeft
  1333.                             Else
  1334.                                 audtTable(intTableNestLevel).lngTableLeft = lngMarginLeft + audtTable(intTableNestLevel).intCellPadding
  1335.                             End If
  1336.                         End If
  1337.                     Else
  1338.                         If intTableNestLevel = 0 Then
  1339.                             audtTable(intTableNestLevel).lngTableLeft = lngMarginLeft
  1340.                         Else
  1341.                             audtTable(intTableNestLevel).lngTableLeft = lngMarginLeft + audtTable(intTableNestLevel).intCellPadding
  1342.                         End If
  1343.                     End If
  1344.                     ' Store the current centreing state.
  1345.                     audtTable(intTableNestLevel).blnCentre = maudtElement(intElem).blnCentre And blnCentre
  1346.                     blnCentre = False
  1347.                     ' Allow tables to be nested.
  1348.                     intTableNestLevel = intTableNestLevel + 1
  1349.                 Case hetTABLEoff
  1350.                     ' Draw the table's border.
  1351.                     If audtTable(intTableNestLevel - 1).intBorderWidth > 0 Then
  1352.                         mRender3DBorder False, _
  1353.                                         audtTable(intTableNestLevel - 1).lngTableLeft, _
  1354.                                         audtTable(intTableNestLevel - 1).lngTableTop, _
  1355.                                         audtTable(intTableNestLevel - 1).lngTableLeft + _
  1356.                                         audtTable(intTableNestLevel - 1).lngTableWidth, _
  1357.                                         audtTable(intTableNestLevel - 1).lngTableTop + _
  1358.                                         audtTable(intTableNestLevel - 1).lngTableHeight
  1359.                     End If
  1360.                     If blnLayoutChanged Then
  1361.                         maudtElement(audtTable(intTableNestLevel - 1).intElement).lngBottom = _
  1362.                             audtTable(intTableNestLevel - 1).lngTableTop + _
  1363.                             audtTable(intTableNestLevel - 1).lngTableHeight - 1 + _
  1364.                         lngLineHeight + clngPadding
  1365.                     End If
  1366.                     ' Allow tables to be nested.
  1367.                     intTableNestLevel = intTableNestLevel - 1
  1368.                     ' Insert vertical spacing after the table.
  1369.                     lngY = lngY + lngLineHeight
  1370.                     ' Reset the left and right margins.
  1371.                     If intTableNestLevel = 0 Then
  1372.                         lngMarginLeft = clngPadding
  1373.                         lngMarginRight = picHTML.ScaleWidth
  1374.                         blnInTable = False
  1375.                     Else
  1376.                         lngMarginLeft = audtTable(intTableNestLevel - 1).lngTableLeft
  1377.                     End If
  1378.                     ' Restore the previous centreing state.
  1379.                     blnCentre = audtTable(intTableNestLevel).blnCentre
  1380.                     lngY = audtTable(intTableNestLevel).lngTableTop + audtTable(intTableNestLevel).lngTableHeight
  1381.                 Case hetTRon
  1382.                     lngX = lngMarginLeft + lngIndent
  1383.                     maudtElement(intElem).lngIndent = lngX - lngMarginLeft
  1384.                     ' Set the row's top edge.
  1385.                     audtTable(intTableNestLevel - 1).lngRowTop = _
  1386.                                 audtTable(intTableNestLevel - 1).lngRowTop + _
  1387.                                 audtTable(intTableNestLevel - 1).lngRowHeight
  1388.                     audtTable(intTableNestLevel - 1).lngRowHeight = _
  1389.                                 audtTable(intTableNestLevel - 1).intCellSpacing / 2
  1390.                     ' Set the first cell's left edge to the row's left edge.
  1391.                     audtTable(intTableNestLevel - 1).lngCellLeft = audtTable(intTableNestLevel - 1).intBorderWidth + _
  1392.                                                                     audtTable(intTableNestLevel - 1).intCellSpacing / 2 + _
  1393.                                                                     audtTable(intTableNestLevel - 1).intBorderWidth
  1394.                     audtTable(intTableNestLevel - 1).intCol = 0
  1395.                 Case hetTRoff
  1396.                     lngX = lngMarginLeft + lngIndent
  1397.                     ' Set the containing table's height.
  1398.                     If audtTable(intTableNestLevel - 1).lngTableHeight + _
  1399.                         audtTable(intTableNestLevel - 1).lngRowHeight > _
  1400.                         audtTable(intTableNestLevel - 1).lngTableHeight Then
  1401.                         audtTable(intTableNestLevel - 1).lngTableHeight = _
  1402.                             audtTable(intTableNestLevel - 1).lngTableHeight + _
  1403.                             audtTable(intTableNestLevel - 1).lngRowHeight + _
  1404.                             audtTable(intTableNestLevel - 1).intCellSpacing \ 2 + _
  1405.                             audtTable(intTableNestLevel - 1).intBorderWidth
  1406.                     End If
  1407.                     ' Draw borders around the cells in the row.
  1408.                     If audtTable(intTableNestLevel - 1).intBorderWidth > 0 Then
  1409.                         Dim idx As Integer
  1410.                         For idx = 0 To audtTable(intTableNestLevel - 1).intCol - 1
  1411.                             mRender3DBorder True, _
  1412.                                             audtTable(intTableNestLevel - 1).audtCol(idx).lngLeft, _
  1413.                                             audtTable(intTableNestLevel - 1).lngRowTop + _
  1414.                                             audtTable(intTableNestLevel - 1).intCellSpacing / 2, _
  1415.                                             audtTable(intTableNestLevel - 1).audtCol(idx).lngRight, _
  1416.                                             audtTable(intTableNestLevel - 1).lngRowTop + _
  1417.                                             audtTable(intTableNestLevel - 1).lngRowHeight
  1418.                         Next idx
  1419.                     End If
  1420.                     ' Adjust the row's height.
  1421.                     audtTable(intTableNestLevel - 1).lngRowHeight = _
  1422.                         audtTable(intTableNestLevel - 1).lngRowHeight + _
  1423.                         audtTable(intTableNestLevel - 1).intCellSpacing / 2 + _
  1424.                         audtTable(intTableNestLevel - 1).intBorderWidth
  1425.                  Case hetTDon
  1426.                     sngCellWidth = maudtElement(intElem).intCellWidth
  1427.                     blnCentre = maudtElement(intElem).blnCentre
  1428.                     ' Set the left and right margins to the cell's left and right edges.
  1429.                     lngMarginLeft = audtTable(intTableNestLevel - 1).lngTableLeft + _
  1430.                                     audtTable(intTableNestLevel - 1).lngCellLeft + _
  1431.                                     audtTable(intTableNestLevel - 1).intCellPadding
  1432.                     lngMarginRight = audtTable(intTableNestLevel - 1).lngTableLeft + _
  1433.                                     audtTable(intTableNestLevel - 1).lngCellLeft + _
  1434.                                     sngCellWidth - _
  1435.                                     audtTable(intTableNestLevel - 1).intCellPadding
  1436.                     audtTable(intTableNestLevel - 1).lngMarginRight = lngMarginRight
  1437.                     lngX = lngMarginLeft
  1438.                     ' Store the cell's left and right margins.
  1439.                     audtTable(intTableNestLevel - 1).audtCol(audtTable(intTableNestLevel - 1).intCol).lngLeft = _
  1440.                         audtTable(intTableNestLevel - 1).lngTableLeft + _
  1441.                         audtTable(intTableNestLevel - 1).lngCellLeft
  1442.                     audtTable(intTableNestLevel - 1).audtCol(audtTable(intTableNestLevel - 1).intCol).lngRight = _
  1443.                         lngMarginRight + _
  1444.                         audtTable(intTableNestLevel - 1).intCellPadding + _
  1445.                         audtTable(intTableNestLevel - 1).intBorderWidth
  1446.                     ' Stretch the containing table to fit the cell.
  1447.                     If audtTable(intTableNestLevel - 1). _
  1448.                         audtCol(audtTable(intTableNestLevel - 1).intCol).lngRight + _
  1449.                         audtTable(intTableNestLevel - 1).intCellSpacing \ 2 + _
  1450.                         audtTable(intTableNestLevel - 1).intBorderWidth - _
  1451.                         audtTable(intTableNestLevel - 1).lngTableLeft > _
  1452.                         audtTable(intTableNestLevel - 1).lngTableWidth Then
  1453.                         audtTable(intTableNestLevel - 1).lngTableWidth = _
  1454.                         audtTable(intTableNestLevel - 1).audtCol(audtTable(intTableNestLevel - 1).intCol).lngRight + _
  1455.                         audtTable(intTableNestLevel - 1).intCellSpacing \ 2 + _
  1456.                         audtTable(intTableNestLevel - 1).intBorderWidth - _
  1457.                         audtTable(intTableNestLevel - 1).lngTableLeft
  1458.                     End If
  1459.                     audtTable(intTableNestLevel - 1).intCol = audtTable(intTableNestLevel - 1).intCol + 1
  1460.                     ' Set y to the containing row's top edge.
  1461.                     lngY = audtTable(intTableNestLevel - 1).lngRowTop + _
  1462.                             audtTable(intTableNestLevel - 1).intCellSpacing / 2 + _
  1463.                             audtTable(intTableNestLevel - 1).intBorderWidth + _
  1464.                             audtTable(intTableNestLevel - 1).intCellPadding
  1465.                 Case hetTDoff
  1466.                     ' Set the containing row's height to the highest cell in the row.
  1467.                     If picHTML.CurrentY + _
  1468.                         audtTable(intTableNestLevel - 1).intCellPadding / 2 + _
  1469.                         audtTable(intTableNestLevel - 1).intBorderWidth - _
  1470.                         audtTable(intTableNestLevel - 1).lngRowTop > _
  1471.                         audtTable(intTableNestLevel - 1).lngRowHeight Then
  1472.                         audtTable(intTableNestLevel - 1).lngRowHeight = _
  1473.                             picHTML.CurrentY + _
  1474.                             audtTable(intTableNestLevel - 1).intCellPadding / 2 + _
  1475.                             audtTable(intTableNestLevel - 1).intBorderWidth - _
  1476.                             audtTable(intTableNestLevel - 1).lngRowTop
  1477.                     End If
  1478.                     ' Set the next cell's left egde.
  1479.                     audtTable(intTableNestLevel - 1).lngCellLeft = _
  1480.                         audtTable(intTableNestLevel - 1).audtCol(audtTable(intTableNestLevel - 1).intCol - 1).lngRight + _
  1481.                         audtTable(intTableNestLevel - 1).intCellSpacing + _
  1482.                         audtTable(intTableNestLevel - 1).intBorderWidth - _
  1483.                         audtTable(intTableNestLevel - 1).lngTableLeft
  1484.                     blnCentre = False
  1485.                 Case hetFONTon
  1486.                     On Error Resume Next
  1487.                     picHTML.FontName = maudtElement(intElem).strFontName
  1488.                     picHTML.FontSize = maudtElement(intElem).sngFontSize
  1489.                     picHTML.ForeColor = maudtElement(intElem).lngFontColor
  1490.                     sngLastFontSize = maudtElement(intElem).sngFontSize
  1491.                 Case hetFONToff
  1492.                     mSetDefaultStyle
  1493.                     sngLastFontSize = msngDefaultFontSize
  1494.                     lngLineHeight = picHTML.TextHeight("X") + clngPadding
  1495.                     lngIndentStep = picHTML.TextWidth("W") * 2
  1496.                 Case hetBLOCKQUOTEon
  1497.                     If blnLayoutChanged Then
  1498.                         lngY = lngY + lngLineHeight
  1499.                         If Not blnSpacerInserted Then
  1500.                             lngY = lngY + lngLineHeight
  1501.                         End If
  1502.                         lngX = lngMarginLeft + lngIndentStep
  1503.                         lngIndent = lngIndent + lngIndentStep
  1504.                         lngLastIndent = lngIndent
  1505.                         maudtElement(intElem).lngIndent = lngLastIndent
  1506.                     End If
  1507.                 Case hetBLOCKQUOTEoff
  1508.                     If blnLayoutChanged Then
  1509.                         lngY = lngY + lngLineHeight
  1510.                         lngX = lngX - lngIndentStep
  1511.                         lngIndent = lngIndent - lngIndentStep
  1512.                         lngLastIndent = lngIndent
  1513.                         maudtElement(intElem).lngIndent = lngLastIndent
  1514.                     End If
  1515.                 Case hetHeaderon
  1516.                     If blnLayoutChanged Then
  1517.                         lngX = lngMarginLeft + lngIndent
  1518.                     End If
  1519.                     picHTML.FontSize = maudtElement(intElem).sngFontSize
  1520.                     picHTML.Font.Bold = True
  1521.                     lngLineHeight = picHTML.TextHeight("X") + clngPadding
  1522.                     lngIndentStep = picHTML.TextWidth("W") * 2
  1523.                     If blnLayoutChanged Then
  1524.                         If picHTML.CurrentY > clngPadding Then
  1525.                             lngY = lngY + lngLineHeight  '+ clngPadding
  1526.                         End If
  1527.                     End If
  1528.                 Case hetBIGon, hetSMALLon
  1529.                     picHTML.FontSize = maudtElement(intElem).sngFontSize
  1530.                 Case hetHeaderoff, hetBIGoff, hetSMALLoff
  1531.                     If blnLayoutChanged Then
  1532.                         lngX = lngMarginLeft + lngIndent
  1533.                         lngY = lngY + lngLineHeight  '- clngPadding
  1534.                     End If
  1535.                     picHTML.FontSize = sngLastFontSize
  1536.                     picHTML.Font.Bold = False
  1537.                     lngLineHeight = picHTML.TextHeight("X") + clngPadding
  1538.                     lngIndentStep = picHTML.TextWidth("W") * 2
  1539.                 Case hetAon
  1540.                     If mblnEnableAnchors Then
  1541.                         If Len(maudtElement(intElem).strAhref) > 0 Then
  1542.                             picHTML.ForeColor = mlngLinkColor
  1543.                             blnStartUnderline = True
  1544.                         End If
  1545.                         intLinkElement = intElem
  1546.                         lngXExtent = lngX
  1547.                     End If
  1548.                 Case hetAoff
  1549.                     If mblnEnableAnchors Then
  1550.                         picHTML.Font.Underline = False
  1551.                         blnStartUnderline = False
  1552.                         picHTML.ForeColor = mlngTextColor
  1553.                         If intLinkElement > -1 Then
  1554.                             If blnLayoutChanged Then
  1555.                                 maudtElement(intLinkElement).lngBottom = lngY + lngLineHeight - clngPadding
  1556.                             End If
  1557.                             maudtElement(intLinkElement).lngRight = lngXExtent
  1558.                             intLinkElement = -1
  1559.                         End If
  1560.                     End If
  1561.                 Case hetIMG
  1562.                     If Len(maudtElement(intElem).strImgAlt) > 0 Then
  1563.                         picHTML.CurrentX = lngX
  1564.                         picHTML.CurrentY = lngY
  1565.                         picHTML.Print "[" & maudtElement(intElem).strImgAlt & "]"
  1566.                         lngX = lngX + picHTML.TextWidth("[" & maudtElement(intElem).strImgAlt & "] ")
  1567.                         lngXExtent = lngX
  1568.                     End If
  1569.                 Case hetCenteron
  1570.                     blnCentre = True
  1571.                     If blnLayoutChanged Then
  1572.                         lngX = lngMarginLeft + lngIndent
  1573.                         maudtElement(intElem).blnCentre = True
  1574.                     End If
  1575.                 Case hetCenteroff
  1576.                     blnCentre = False
  1577.                     If blnLayoutChanged Then
  1578.                         lngX = lngMarginLeft + lngIndent
  1579.                         maudtElement(intElem).blnCentre = False
  1580.                     End If
  1581.                 Case Else
  1582.             End Select
  1583.         ElseIf Not blnIgnore Then
  1584.             If blnLayoutChanged Then
  1585.                 maudtElement(intElem).lngLeft = lngX
  1586.                 maudtElement(intElem).lngIndent = lngLastIndent
  1587.             End If
  1588.             ' Render the content according to the prevailing mark-up.
  1589.             If maudtElement(intElem).blnCentre Then
  1590.                 ' Centre the next content string.
  1591.                 intWord = 0
  1592.                 While intWord <= UBound(maudtElement(intElem).astrWords)
  1593.                     ' Add the next word to the line text.
  1594.                     strValue = maudtElement(intElem).astrWords(intWord)
  1595.                     intWord = intWord + 1
  1596.                     If intWord <= UBound(maudtElement(intElem).astrWords) Then
  1597.                         Do While picHTML.TextWidth(strValue & " " & maudtElement(intElem).astrWords(intWord)) <= _
  1598.                               lngMarginRight - (clngPadding * 2)
  1599.                             ' Build the longest string which will fit onto a single line.
  1600.                             strValue = strValue & " " & maudtElement(intElem).astrWords(intWord)
  1601.                             intWord = intWord + 1
  1602.                             If intWord > UBound(maudtElement(intElem).astrWords) Then
  1603.                                 Exit Do
  1604.                             End If
  1605.                         Loop
  1606.                     End If
  1607.                     
  1608.                     ' Output the string centred.
  1609.                     picHTML.CurrentY = lngY
  1610.                     picHTML.CurrentX = (((lngMarginRight - lngMarginLeft - (clngPadding * 2)) - _
  1611.                                        picHTML.TextWidth(strValue)) / 2) + lngMarginLeft
  1612.                     lngX = picHTML.CurrentX
  1613.                     If intLinkElement > -1 Then
  1614.                         If blnLayoutChanged Then
  1615.                             maudtElement(intLinkElement).lngTop = lngY
  1616.                         End If
  1617.                         lngXExtent = lngX & picHTML.TextWidth(strValue)
  1618.                     End If
  1619.                     picHTML.Print strValue
  1620.                     blnSpacerInserted = False
  1621.                     lngY = lngY + lngLineHeight
  1622.                Wend
  1623.             Else
  1624.                 ' Output the next content string (non-centred).
  1625.                 For intWord = 0 To UBound(maudtElement(intElem).astrWords)
  1626.                     If lngX = maudtElement(intElem).lngIndent + lngMarginLeft Or _
  1627.                         Len(maudtElement(intElem).astrWords(intWord)) = 0 Or _
  1628.                         Left(maudtElement(intElem).astrWords(intWord), 1) = "." Or _
  1629.                         Left(maudtElement(intElem).astrWords(intWord), 1) = "," Or _
  1630.                         lngX = lngMarginLeft + clngPadding Then
  1631.                         ' Do not insert a space at the beginning of lines, sentences, etc.
  1632.                         strValue = ""
  1633.                     Else
  1634.                         ' Insert a space between each word.
  1635.                         strValue = " "
  1636.                     End If
  1637.                     strValue = strValue & Replace(Replace(maudtElement(intElem).astrWords(intWord), "  ", " "), "  ", " ")
  1638.                     If lngX + picHTML.TextWidth(strValue) >= lngMarginRight - clngPadding Then
  1639.                         If Left(strValue, 1) = " " Then
  1640.                             strValue = Mid(strValue, 2)
  1641.                         End If
  1642.                         lngXExtent = lngMarginRight - clngPadding
  1643.                         ' Wrap to the next line.
  1644.                         lngX = lngMarginLeft + maudtElement(intElem).lngIndent
  1645.                         lngY = lngY + lngLineHeight
  1646.                         If intLinkElement > -1 And intWord = 0 Then
  1647.                             If blnLayoutChanged Then
  1648.                                 maudtElement(intLinkElement).lngTop = lngY
  1649.                             End If
  1650.                             maudtElement(intLinkElement).lngLeft = lngX
  1651.                         End If
  1652.                         picHTML.CurrentX = lngX
  1653.                         picHTML.CurrentY = lngY
  1654.                         If blnStartUnderline Then
  1655.                             If Left(strValue, 1) = " " Then
  1656.                                 picHTML.Print " ";
  1657.                                 lngX = lngX + picHTML.TextWidth(" ")
  1658.                                 strValue = Mid(strValue, 2)
  1659.                             End If
  1660.                             picHTML.FontUnderline = True
  1661.                             blnStartUnderline = False
  1662.                         End If
  1663.                             
  1664.                         picHTML.Print strValue
  1665.                         lngX = lngX + picHTML.TextWidth(strValue)
  1666.                         If intLinkElement > -1 And intWord = 0 Then
  1667.                             lngXExtent = lngX
  1668.                         End If
  1669.                         blnSpacerInserted = False
  1670.                     ElseIf Len(strValue) > 0 Then
  1671.                         ' Output the next word.
  1672.                         picHTML.CurrentX = lngX
  1673.                         picHTML.CurrentY = lngY
  1674.                         If blnStartUnderline Then
  1675.                             If Left(strValue, 1) = " " Then
  1676.                                 picHTML.Print " ";
  1677.                                 lngX = lngX + picHTML.TextWidth(" ")
  1678.                                 strValue = Mid(strValue, 2)
  1679.                             End If
  1680.                             picHTML.FontUnderline = True
  1681.                             blnStartUnderline = False
  1682.                         End If
  1683.                         picHTML.Print strValue
  1684.                         lngX = lngX + picHTML.TextWidth(strValue)
  1685.                         lngXExtent = IIf(lngXExtent > lngX, lngXExtent, lngX)
  1686.                         blnSpacerInserted = False
  1687.                     End If
  1688.                 Next intWord
  1689.             End If
  1690.         End If
  1691.         If blnLayoutChanged And maudtElement(intElem).hetType <> hetCommenton Then
  1692.             maudtElement(intElem).lngBottom = lngY + lngLineHeight + clngPadding
  1693.             maudtElement(intElem).lngRight = lngXExtent
  1694.         End If
  1695.         intElem = intElem + 1
  1696.     Loop
  1697. ExitPoint:
  1698.     Exit Sub
  1699. ErrorHandler:
  1700.     Resume ExitPoint
  1701. End Sub
  1702. ' mlngTranslateHTMLColour()
  1703. ' Translate the specified HTML colour name into a suitable RGB colour value.
  1704. ' strColourName :   The name of the colour to be translated.
  1705. Private Function mlngTranslateHTMLColour(strColourName As String) As Long
  1706.     Dim strRGB      As String
  1707.     Select Case LCase(strColourName)
  1708.         Case "black"
  1709.             strRGB = "000000"
  1710.         Case "green"
  1711.             strRGB = "008000"
  1712.         Case "silver"
  1713.             strRGB = "C0C0C0"
  1714.         Case "lime"
  1715.             strRGB = "00FF00"
  1716.         Case "gray"
  1717.             strRGB = "808080"
  1718.         Case "olive"
  1719.             strRGB = "808000"
  1720.         Case "white"
  1721.             strRGB = "FFFFFF"
  1722.         Case "yellow"
  1723.             strRGB = "FFFF00"
  1724.         Case "maroon"
  1725.             strRGB = "800000"
  1726.         Case "navy"
  1727.             strRGB = "000080"
  1728.         Case "red"
  1729.             strRGB = "FF0000"
  1730.         Case "blue"
  1731.             strRGB = "0000FF"
  1732.         Case "purple"
  1733.             strRGB = "800080"
  1734.         Case "teal"
  1735.             strRGB = "008080"
  1736.         Case "fuchsia"
  1737.             strRGB = "FF00FF"
  1738.         Case "aqua"
  1739.             strRGB = "00FFFF"
  1740.         Case Else
  1741.             strRGB = "000000"
  1742.     End Select
  1743.     mlngTranslateHTMLColour = RGB(CLng("&H" & Left(strRGB, 2)), _
  1744.                               CLng("&H" & Mid(strRGB, 3, 2)), _
  1745.                               CLng("&H" & Right(strRGB, 2)))
  1746. End Function
  1747. ' mRender3DBorder()
  1748. ' Draw a 3D border around the specified rectangle.
  1749. Private Sub mRender3DBorder(blnInset As Boolean, lngLeft As Long, lngTop As Long, lngRight As Long, lngBottom As Long)
  1750.     Dim lngCol  As Long
  1751.     lngCol = picHTML.ForeColor
  1752.     If blnInset Then
  1753.         picHTML.ForeColor = vbButtonShadow
  1754.     Else
  1755.         If picHTML.BackColor = vbWhite Then
  1756.             picHTML.ForeColor = vbButtonFace
  1757.         Else
  1758.             picHTML.ForeColor = vbWhite
  1759.         End If
  1760.     End If
  1761.     picHTML.Line (lngLeft, lngTop)-(lngRight, lngTop)
  1762.     picHTML.Line (lngLeft, lngTop)-(lngLeft, lngBottom)
  1763.     If blnInset Then
  1764.         If picHTML.BackColor = vbWhite Then
  1765.             picHTML.ForeColor = vbButtonFace
  1766.         Else
  1767.             picHTML.ForeColor = vbWhite
  1768.         End If
  1769.     Else
  1770.         picHTML.ForeColor = vbButtonShadow
  1771.     End If
  1772.     picHTML.Line (lngRight, lngTop)-(lngRight, lngBottom)
  1773.     picHTML.Line (lngLeft, lngBottom)-(lngRight + 1, lngBottom)
  1774.     picHTML.ForeColor = lngCol
  1775. End Sub
  1776. ' mBuildHierarchy()
  1777. ' Structure the elements array as a hierarchy,.
  1778. Public Sub mBuildHierarchy()
  1779.     If mintElements > 0 Then
  1780.         maudtElement(0).intChildElements = mBuildElementHierarchy(0, maudtElement(0))
  1781.     End If
  1782. End Sub
  1783. ' mBuildElementHierarchy()
  1784. ' Structure the specified HTML element as a hierarchy.
  1785. Private Function mBuildElementHierarchy(ByRef intElem As Integer, ByRef udtElem As tHTMLElement) As Integer
  1786.     Dim intChildElem    As Integer
  1787.     Do While intElem < mintElements
  1788.         intElem = intElem + 1
  1789.         If intElem >= mintElements Then
  1790.             Exit Do
  1791.         End If
  1792.         ReDim Preserve udtElem.aintChildElements(intChildElem)
  1793.         udtElem.aintChildElements(intChildElem) = intElem
  1794.         maudtElement(intElem).intParentElement = udtElem.intElementIndex
  1795.         maudtElement(intElem).intChildIndex = intChildElem
  1796.         If maudtElement(intElem).blnIsTag Then
  1797.             Select Case maudtElement(intElem).hetType
  1798.                 Case hetHEADon, hetTITLEon, hetBODYon, hetSTRONGon, hetEMon, hetUon, hetPon, _
  1799.                         hetULon, hetOLon, hetTABLEon, hetTRon, hetTDon, hetFONTon, hetAon, hetBLOCKQUOTEon, _
  1800.                         hetHeaderon, hetBIGon, hetSMALLon, hetCenteron
  1801.                     maudtElement(udtElem.aintChildElements(intChildElem)).intChildElements = _
  1802.                         mBuildElementHierarchy(intElem, maudtElement(intElem))
  1803.                 Case hetHEADoff, hetTITLEoff, hetBODYoff, hetSTRONGoff, hetEMoff, hetUoff, hetPoff, _
  1804.                         hetULoff, hetOLoff, hetTABLEoff, hetTDoff, hetFONToff, hetAoff, hetBLOCKQUOTEoff, _
  1805.                         hetHeaderoff, hetBIGoff, hetSMALLoff, hetCenteroff
  1806.                     Exit Do
  1807.                 Case hetTRoff
  1808.                     Exit Do
  1809.             End Select
  1810.         End If
  1811.         intChildElem = intChildElem + 1
  1812.     Loop
  1813.     On Error Resume Next
  1814.     mBuildElementHierarchy = intChildElem
  1815. End Function
  1816. ' mblnGetParent()
  1817. ' Return the immediate parent of udtIn as udtOut.
  1818. ' Returns True if successful, False otherwise.
  1819. Private Function mblnGetParent(ByRef udtIn As tHTMLElement, ByRef udtOut As tHTMLElement) As Boolean
  1820.     If udtIn.intParentElement > 0 Then
  1821.         udtOut = maudtElement(udtIn.intParentElement)
  1822.         mblnGetParent = True
  1823.     Else
  1824.         mblnGetParent = False
  1825.     End If
  1826. End Function
  1827. ' mblnGetFirstChild()
  1828. ' Return the first child of udtIn as udtOut.
  1829. ' Returns True if successful, False otherwise.
  1830. Private Function mblnGetFirstChild(ByRef udtIn As tHTMLElement, ByRef udtOut As tHTMLElement) As Boolean
  1831.     If udtIn.intChildElements > 0 Then
  1832.         udtOut = maudtElement(udtIn.aintChildElements(0))
  1833.         mblnGetFirstChild = True
  1834.     Else
  1835.         mblnGetFirstChild = False
  1836.     End If
  1837. End Function
  1838. ' mblnGetNextSibling()
  1839. ' Return the next sibling of udtIn as udtOut.
  1840. ' Returns True if successful, False otherwise.
  1841. Private Function mblnGetNextSibling(ByRef udtIn As tHTMLElement, ByRef udtOut As tHTMLElement) As Boolean
  1842.     Dim udtTemp As tHTMLElement
  1843.     If mblnGetParent(udtIn, udtTemp) Then
  1844.         If udtIn.intChildIndex + 1 < udtTemp.intChildElements Then
  1845.             udtOut = maudtElement(udtTemp.aintChildElements(udtIn.intChildIndex + 1))
  1846.             mblnGetNextSibling = True
  1847.         Else
  1848.             mblnGetNextSibling = False
  1849.         End If
  1850.     Else
  1851.         mblnGetNextSibling = False
  1852.     End If
  1853. End Function
  1854. ' mLayoutTable()
  1855. ' Calculate the width of the specified TABLE element and its contained TD elements.
  1856. Private Sub mLayoutTable(ByRef udtTable As tHTMLElement)
  1857.     Dim blnFound                        As Boolean
  1858.     Dim intTableCols                    As Integer
  1859.     Dim intColIndex                     As Integer
  1860.     Dim intColSpan                      As Integer
  1861.     Dim intUnsizedCols                  As Integer
  1862.     Dim lngAvailWidth                   As Long
  1863.     Dim sngTotalWidth                   As Single
  1864.     Dim asngColWidth(m/s sngTotalWid  As Integer
  1865.     Dim lngAvailWidth L    mblnGetParent = False
  1866.     E             CLng(    s Single
  1867.     Dim asngCollWidth(m/s      s Si
  1868.                     maud intElem < miOut As Dim lngAvailWidth L    mblnGetPm        udtOut = maudtElement(udtIn.aintChildElementsaderoff, hetBImBuildHierarchs       nhmntChildElem =         Case hetTDoff
  1869.  srchsUGetParent = False
  1870.     E       i0         vAonnchors Then
  1871. In.aimaubs            Aonnchors Then
  1872. In.aimaubs            AonncudtElement(intColSpan   Table(intTableNe
  1873.        n.aimaubs            AonnchintTableNestLevel).lngTableHeight =pLn.aimaubs            AonncgTableHeight =pLn.aimaubs          vxtSibling = False
  1874.       /vel - 1).intETC  Case hetTRofF/           lngo         End Select
  1875.         End If
  1876.         intChildElemTIdHierig(    s Si N            If Left(stng = False
  1877.       /vel - 1).int
  1878.                 n As tHTMLElement, ByRef udtOut As tHTMLElement) As Bool(audtElement(intElem).blnIsTag Then
  1879.   c    AsnEnd Iction mblnGeht =pLn.aimaubs          vxtSibling = False
  1880.            Underline = False
  1881.       IocGB = "808080"
  1882.   TML.Forw=s1 specified rectangle.
  1883. '     f, hetUlnStartUnderline Then
  1884.       =ng + _
  1885.                         audtTable(intTableNestLevel - 1).intBorderWidth - _
  1886.                         audtTable(intTableNestLevel - 1).lngTableL             nd Iction mblnGeht = As Boolean
  1887.     Dim End If
  1888.      Lng = FblnGetPar which will fit onto a single l 
  1889.           IocGB = "808080"
  1890.   TmAs Integer
  1891.     DiR udtIn.intParentElement >     audtTable(intTableNestLevel - 1).lngTableHeightWidth   era   06u(nfelement >    06u(nfelement >    06u(nfelementel - 1).lngTH ementel - 1)eturns True if successful, False otherwise.
  1892. Private Function mblnGetFirstChild(ByteNestion mblnGetFirstChild(ByteNestihildElem)).intChildElements = _
  1893.     rderWidth - _
  1894.             tkent >    06u(nfelementel - 1).lngTH emW") * 2
  1895.                 Case hetAon
  1896.                     If mblo           Case hetAon
  1897.            =Hpp Function
  1898.  s Si
  1899.                     maud int                      I*False otheo          e Then
  1900.                               maud int                     e he' mBuiabs             I*False otheo          e Then
  1901.                               maud int                     e he' mBuiabs             I*False otheo          e Then
  1902.                               maud int         e otheo          e Then
  1903.           haip'
  1904. 'lnGetFirstChiClUnt      ngTH ementel - 1)e  Dim intTableCols                    As Integer
  1905.     Dim intColIndex                     As Integer
  1906.     Dim intColSpan                      As Integerx    maud Ll -se.
  1907. Pr)abllmaud int                      I*False otheo          e Then
  1908.                               maud int                     e he' mBuiabs             I*False otheo          e Then
  1909.                               maud int                     e he' mBuiabs         N6ieeeeeeeeecent = False
  1910.     E    ae hetHE _
  1911.                      intWord = 0
  1912. BrderWidth - _
  1913.        etFirstChiClUnt      ngTH ementel - 1)e  Dim intTableCols                    As Integer
  1914.     Dim intColIndex                     As Integer
  1915.     Dim intColSpan             ntTa dHierarchy()
  1916.     If mintElan     ments(intftLinkEl1ble(inlTn       BuildETBLE element and its contained TDble(intTableNestLevel - 1).ament and its contained TDble(intTableNestLevel - 1).ament and its contain Dim End Ifm asngCollWidto dHrr            bu.Table(inn
  1917.           
  1918.       IocGB = "808080"
  1919.   TML.Forw=s1 specified rectangs Dim lngAvailWidth L    t     )ht Us contain Dim End Ifm asngCollWidto dHrr            bu.    =                       maud int   r   - 1).
  1920.     intTableCols                    As Integn   N    A1     maud int           e he' mBuiabs     m iin    If picHTML.BackColor = vbWhite ThendtTab       e Then
  1921. u    icHTML.BackColor = vbWhite ThendtTab       eintTableCo  If pic     mauf
  1922.             As Integer
  1923.     Dim intUnsizedCol           AsastrV"l          hildElements(0))
  1924.         mblen'
  1925. 'lnGet                     End IIIIIIIIIIIIIIIIIIIIII-tnts(0))
  1926. yvel               e he' mBuiabs         N6ieeeeeeeeecent = False
  1927.     E    ae hetHE _
  1928.               - 1).R = False
  1929.     E       i0  f              - 1).R = Falst and its contain'
  1930. 'lnGet                     End IIIIIIIIIIIIIse.
  1931. Pr)abllmaud int               t and its contn'
  1932. 'lnGet            If Left(stng = False
  1933.       /vel - 1).int
  1934.                 n As tHTMLElement, ByRe     l = picHTML.ForeColorim intColIndex   tment, ByRe   tldElemTIdH As Boolean
  1935. TDble(intT = lnt, ByRe     l blnIrhrue
  1936.  ByRe S      d
  1937.  If picHTML.BackColor = vbWhite o  s intCol  tmCase hetAon
  1938.    HTDble-u         ttHTDOut As tHolSpan   RCasef    E    ae hetHE _
  1939.  tmElemTIdH As Boole= aue next sibling of udtIn ed.
  1940. HTML.Prc
  1941. HTMIndex   tment, ByRe   tldElemTIdH As Boolean
  1942. TDblrR'
  1943. 'lnGeudtTemp.intChildEle+v
  1944. =Go       rs             I*Falsee"
  1945.      dtTe      emTIdH     
  1946.       IocGB = "80ntTablen = "80pe.
  1947. Private Functi Oip
  1948. =Go       rs             I*FalML.Print s       I*Falsee"
  1949.      dtTe      emTItain Dim End Ifm asngCollWidt      inrWemTIFalML.Print s       I*Falsee"
  1950.      dtTe      emTItain Dim End Ifm asngCollWidt   wkLeft(stng = YIdH   Widt   wkLeft(stlp
  1951. =Go       rs               n        wk   RCasef    E    ae hetHE rD=yRer"     ngTH                             w    gintElem).sngFontSain'
  1952. 'lnGet                     End IIIIIIIIIIIIIsetTemp As tHTMLElement
  1953.     If mblnGetParent(udtRolorim intColIndex   RnGeudtTemp.intChildEle+v
  1954. =Go       rs             I*Falsee"
  1955.      dtTe      emTIdH     
  1956.       IocGB = "80ntTable       0intT = lnt, ByRe     l blnIrhrue
  1957. Pr)abllmaudddddddddddddddddddd0                     lngX = lngMarginLeft + lngIndent
  1958.   sa   emi    inLeft + lv  I*tTe 
  1959. Pr)abllmaud int                      I*False otheo         mL      CaseR80"
  1960.   eeML.PrinColSpan                      As Integerx    maud Ll -se.
  1961. Pr)abllmaud inrpel - 1)maud L     
  1962.